﻿using MachineLearning.ClusteringProblem.NumberGenerator;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ClusteringProblem.Model
{
    /// <summary>
    /// Klasa reprezentująca wirtualnego agenta
    /// </summary>
    public class AntType : IAntType
    {
        #region Pola

        private double[] vector;
        private int radius;
        private int index;
        private static int groupIDCounter = 1;

        private string resultGroupID;
        private string objectID;
        private Object _object;

        private MersenneTwister random = new MersenneTwister();
        private static Dictionary<string, string> groupsID = new Dictionary<string, string>();                        

        #endregion

        public AntType(Object _object)
        {
            if (!groupsID.ContainsKey(_object.GroupID.ToString()))
            {
                groupsID.Add(_object.GroupID.ToString(), groupIDCounter.ToString());
                groupIDCounter++;
            }

            ResultGroupID = groupsID[_object.GroupID.ToString()];

            this._object = _object;
            Vector = _object.Values.OrderBy(x => x.VectorOrder)
                                     .Select(x => x.Feature)
                                     .ToArray<double>();           
        }

        #region Właściowści

        public string ResultGroupID
        {
            get
            {
                return resultGroupID;
            }
            set
            {
                resultGroupID = value;
            }
        }

        public double[] Vector
        {
            get
            {
                return vector;
            }
            set
            {
                vector = value;
            }
        }

        public int X
        {
            get; set;
        }

        public int Y
        {
            get; set;
        }

        public int Index
        {
            get
            {
                return index;
            }
            set
            {
                index = value;
            }
        }

        public int Radius
        {
            get
            {
                return radius;
            }
            set
            {
                radius = value;
            }
        }

        public string ObjectID
        {
            get
            {
                return _object.ID.ToString();
            }            
        }

        #endregion

        #region Metody

        public void Move(Plane plane, double x, double y)
        {
            if ((int)Math.Abs(x) < 1 && (int)Math.Abs(y) < 1)
                return;

            plane[X, Y] = null;

            X = EnsureToroidal(X + (int)x, plane.Size);
            Y = EnsureToroidal(Y + (int)y, plane.Size);

            while (!plane.isOccupied(X, Y))
            {
                if (random.NextDouble() > 0.5)
                    X = random.NextDouble() > 0.5 ? X + 1 : X - 1;
                else
                    Y = random.NextDouble() > 0.5 ? Y + 1 : Y - 1;

                X = EnsureToroidal(X, plane.Size);
                Y = EnsureToroidal(Y, plane.Size);
            }

            plane[X, Y] = this;
        }

        private int EnsureToroidal(int p1, int size)
        {
            while (p1 < 0)
                p1 = size + p1;

            while (p1 >= size)
                p1 = p1 - size;

            return p1;
        }

        #endregion        
    }
}
